package DRC;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import DRCOMM.DRHTTP_API;
import DRCOMM.DR_SESSION;
import DRCOMM.FJW_URI;
import DRCOMM.dr_ajax_answer;
import DRCOMM.record_data_set;

public class dataSimulator extends Thread{

    public final static int DATA_TYPE_INT=1;
    public final static int DATA_TYPE_FLOAT=2;

    public final static int METHOD_INCREMENT=1;
    public final static int METHOD_RANDOM=2;
    public final static int METHOD_LIST=3;
    
    public static DRCDB drcdb=null;
    public static ArrayList<channel> channels=null;
    public int data_simulator_id=-1;
    public int address=0;
    public int data_count=1;
    public float data_start=0;    // start value of data
    public float data_end=100;    // end value of data
    public int data_type=1;        // data type: 1-integer, 2-float
    public int method=1;          // method to generate data: 1-递增, 2-随机, 3-列表循环
    public int run_cycle=1000;
    public float[] data_list=null;    // data list for method 3
    public boolean run_mark=false;

    private static Map<String,Thread> dataSimulator_run_list=new HashMap<String,Thread>();

    /**
     * 构造函数
     * @param address    起始地址
     * @param count       数据大小
     * @param start      起始值
     * @param end        结束值
     * @param type       数据类型   1-integer, 2-float
     * @param method     生成方法   1-递增, 2-随机, 3-列表循环
     * @param cycle      运行周期
     * @param list       数据列表
     */
    public dataSimulator(int address, int count, float start, float end, int type, int method, int cycle, float[] list) {
        this.address=address;
        this.data_count=count;
        this.data_start=start;
        this.data_end=end;
        this.data_type=type;
        this.method=method;
        this.run_cycle=cycle;
        this.data_list=list;
    }

    public boolean write2database(){
        String sqlstr=null;
        if(data_simulator_id==-1){
            sqlstr=String.format("INSERT INTO data_simulator (address,data_count,data_start,data_end,data_type,method,run_cycle) VALUES (%d,%d,%d,%d,%d,%d,%d)",
                this.address,this.data_count,this.data_start,this.data_end,this.data_type,this.method,this.run_cycle);
        }else{
            sqlstr="update data_simulator";
            sqlstr+=" set address="+this.address+",data_count="+this.data_count;
            sqlstr+=",data_start="+this.data_start+",data_end="+this.data_end;
            sqlstr+=",data_type="+this.data_type+",method="+this.method;
            sqlstr+=",run_cycle="+this.run_cycle;
            sqlstr+=" where id="+this.data_simulator_id;
        }
        return drcdb.executeUpdateSQL(sqlstr);
    }

    public static ArrayList<dataSimulator> read_data_simulators(){
        ArrayList<dataSimulator> simulators=new ArrayList<dataSimulator>();
        String sqlstr=String.format("SELECT * FROM data_simulator");
        record_data_set rds=drcdb.executeQuerySQL(sqlstr);
        for(Map<String,String> data:rds.datas){
            int address=Integer.parseInt(data.get("address"));
            int size=Integer.parseInt(data.get("data_count"));
            float start=Float.parseFloat(data.get("data_start"));
            float end=Float.parseFloat(data.get("data_end"));
            int type=Integer.parseInt(data.get("data_type"));
            int method=Integer.parseInt(data.get("method"));
            int cycle=Integer.parseInt(data.get("run_cycle"));
            dataSimulator ds=new dataSimulator(address,size,start,end,type,method,cycle,null);
            simulators.add(ds);
        }
        return simulators;
    }

    /**
     * 生成数据
     */
    public void generateData() {
        channel ch=channels.get(0);
        int data_list_index=0;
        while(this.run_mark){
            for(int i=this.address;i<(this.address+this.data_count);i++){
                dataItem di=ch.dataItems.get(i);
                if(this.method==1){
                    di.value=di.value+1;
                    if(di.value>this.data_end)di.value=this.data_start;
                }else if(this.method==2){
                    if(this.data_type==1){
                        di.value=(int)(Math.random()*(this.data_end-this.data_start)+this.data_start);
                    }else{
                        di.value=(float)(Math.random()*(this.data_end-this.data_start)+this.data_start);
                    }
                }else if(this.method==3){
                    if(this.data_list==null)continue;
                    if(data_list_index>=this.data_list.length)data_list_index=0;
                    di.value=this.data_list[data_list_index];
                    data_list_index++;
                }
            }
            System.out.println("DataSimulator: generate data");
            try {
                Thread.sleep(this.run_cycle);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void run(){
        generateData();
    }

    /**
     * 根据数据库启动所有DataSimulator线程
     */
    public static void auto_start(){
        ArrayList<dataSimulator> simulators=read_data_simulators();
        for(dataSimulator ds:simulators){
            ds.run_mark=true;
            ds.start();
        }
    }

    /**
     * 关联WEB API列表
     * @param api_lists
     * @param fpsdb
     * @param drcdb
     */
    public static void associate_actions(List<DRHTTP_API> api_lists,DRCDB drcdb) throws ClassNotFoundException{
        @SuppressWarnings("unchecked")
        Class<?> CLS=(Class<dataSimulator>) Class.forName("DRC.dataSimulator");
        for(Method method:CLS.getDeclaredMethods()){
            FJW_URI fjw_uri=method.getAnnotation(FJW_URI.class);
            System.out.println(method.toString());
            if(fjw_uri!=null){
                System.out.println(method.toString());
                System.out.println(fjw_uri.value());
                try {
                    api_lists.add((DRHTTP_API)method.invoke(CLS,drcdb, fjw_uri.value()));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @FJW_URI(value ="dataSimulator/dataSimulatorList")
    public static DRHTTP_API dataSimulatorList(DRCDB drcdb,String URI){
        return new DRHTTP_API(drcdb,URI){
            @Override
            public String getResult(Map<String, Object> parameters,DR_SESSION drs){
                String content="";
                DRCDB db=drcdb;
                String sqlstr="select * from data_simulator order by data_simulator_id";
                record_data_set rds=db.executeQuerySQL(sqlstr);
                content=record_data_set.get_answer_json_str(0,"",rds);
                return content;
            }
        };
    }

    @FJW_URI(value ="dataSimulator/readDataSimulator")
    public static DRHTTP_API read_data_simulator(DRCDB drcdb,String URI){
        return new DRHTTP_API(drcdb,URI){
            @Override
            public String getResult(Map<String, Object> parameters,DR_SESSION drs){
                String content="";
                String data_simulator_id=this.get_parameters(parameters,"data_simulator_id");
                DRCDB db=drcdb;
                String sqlstr="select * from data_simulator";
                sqlstr+=String.format(" where data_simulator_id=%s",data_simulator_id);
                record_data_set rds=db.executeQuerySQL(sqlstr);
                content=record_data_set.get_answer_json_str(0,"",rds);
                return content;
            }
        };
    }

    @FJW_URI(value ="dataSimulator/saveDataSimulator")
    public static DRHTTP_API save_data_simulator(DRCDB drcdb,String URI){
        return new DRHTTP_API(drcdb,URI){
            @Override
            public String getResult(Map<String, Object> parameters,DR_SESSION drs){
                String content="";
                String data_simulator_id=this.get_parameters(parameters,"data_simulator_id");
                String address=this.get_parameters(parameters,"address");
                String data_count=this.get_parameters(parameters,"data_count");
                String data_start=this.get_parameters(parameters,"data_start");
                String data_end=this.get_parameters(parameters,"data_end");
                String data_type=this.get_parameters(parameters,"data_type");
                String method=this.get_parameters(parameters,"method");
                String run_cycle=this.get_parameters(parameters,"run_cycle");
                // String enable=this.get_parameters(parameters,"enable");
                DRCDB db=drcdb;
                String sqlstr;
                boolean result=false;
                // enable=(enable.length()>0)?"1":"0";
                if(data_simulator_id==null||data_simulator_id==""){
                    sqlstr="insert into data_simulator(address,data_count,data_start,data_end,data_type,method,run_cycle)";
                    sqlstr+=String.format(" values(%s,%s,%s,%s,%s,%s,%s)",address,data_count,data_start,data_end,data_type,method,run_cycle);
                }else{
                    sqlstr="update data_simulator";
                    sqlstr+=String.format(" set address=%s",address);
                    sqlstr+=String.format(",data_count=%s",data_count);
                    sqlstr+=String.format(",data_start=%s",data_start);
                    sqlstr+=String.format(",data_end=%s",data_end);
                    sqlstr+=String.format(",data_type=%s",data_type);
                    sqlstr+=String.format(",method=%s",method);
                    sqlstr+=String.format(",run_cycle=%s",run_cycle);
                    sqlstr+=String.format(" where data_simulator_id=%s" , data_simulator_id);
                }
                result=db.executeUpdateSQL(sqlstr);
                if(result){
                    content=dr_ajax_answer.sample_json_string(0,"");
                }else{
                    content=dr_ajax_answer.sample_json_string(1,"保存失败！");
                }
                return content;
            }
        };
    }

    @FJW_URI(value ="dataSimulator/delDataSimulator")
    public static DRHTTP_API del_dataSimulator(DRCDB drcdb,String URI){
        return new DRHTTP_API(drcdb,URI){
            @Override
            public String getResult(Map<String, Object> parameters,DR_SESSION drs){
                String content="";
                String data_simulator_id=this.get_parameters(parameters,"data_simulator_id");
                boolean result=false;
                DRCDB db=drcdb;
                String sqlstr;
                sqlstr="delete from data_simulator";
                sqlstr+=String.format(" where data_simulator_id=%s" , data_simulator_id);
                result=db.executeUpdateSQL(sqlstr);
                sqlstr="delete from dataItem";
                sqlstr+=String.format(" where data_simulator_id=%s" , data_simulator_id);
                result=db.executeUpdateSQL(sqlstr);
                if(result){
                    content=dr_ajax_answer.sample_json_string(0,"");
                }else{
                    content=dr_ajax_answer.sample_json_string(1,"保存失败！");
                }
                return content;
            }
        };
    }


}
